1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.apache.tapestry5.internal.plastic.asm.optimizer;
31
32 import java.util.HashMap;
33
34 import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
35 import org.apache.tapestry5.internal.plastic.asm.Attribute;
36 import org.apache.tapestry5.internal.plastic.asm.FieldVisitor;
37 import org.apache.tapestry5.internal.plastic.asm.Label;
38 import org.apache.tapestry5.internal.plastic.asm.MethodVisitor;
39 import org.apache.tapestry5.internal.plastic.asm.Opcodes;
40 import org.apache.tapestry5.internal.plastic.asm.Type;
41 import org.apache.tapestry5.internal.plastic.asm.TypePath;
42 import org.apache.tapestry5.internal.plastic.asm.commons.Remapper;
43 import org.apache.tapestry5.internal.plastic.asm.commons.RemappingMethodAdapter;
44
45
46
47
48
49
50
51 public class MethodOptimizer extends RemappingMethodAdapter implements Opcodes {
52
53 private final ClassOptimizer classOptimizer;
54
55 public MethodOptimizer(ClassOptimizer classOptimizer, int access,
56 String desc, MethodVisitor mv, Remapper remapper) {
57 super(Opcodes.ASM5, access, desc, mv, remapper);
58 this.classOptimizer = classOptimizer;
59 }
60
61
62
63
64
65 @Override
66 public void visitParameter(String name, int access) {
67
68 }
69
70 @Override
71 public AnnotationVisitor visitAnnotationDefault() {
72
73 return null;
74 }
75
76 @Override
77 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
78
79 return null;
80 }
81
82 @Override
83 public AnnotationVisitor visitTypeAnnotation(int typeRef,
84 TypePath typePath, String desc, boolean visible) {
85 return null;
86 }
87
88 @Override
89 public AnnotationVisitor visitParameterAnnotation(final int parameter,
90 final String desc, final boolean visible) {
91
92 return null;
93 }
94
95 @Override
96 public void visitLocalVariable(final String name, final String desc,
97 final String signature, final Label start, final Label end,
98 final int index) {
99
100 }
101
102 @Override
103 public void visitLineNumber(final int line, final Label start) {
104
105 }
106
107 @Override
108 public void visitFrame(int type, int local, Object[] local2, int stack,
109 Object[] stack2) {
110
111 }
112
113 @Override
114 public void visitAttribute(Attribute attr) {
115
116 }
117
118 @Override
119 public void visitLdcInsn(Object cst) {
120 if (!(cst instanceof Type)) {
121 super.visitLdcInsn(cst);
122 return;
123 }
124
125
126 String ldcName = ((Type) cst).getInternalName();
127 String fieldName = "class$" + ldcName.replace('/', '$');
128 if (!classOptimizer.syntheticClassFields.contains(ldcName)) {
129 classOptimizer.syntheticClassFields.add(ldcName);
130 FieldVisitor fv = classOptimizer.syntheticFieldVisitor(ACC_STATIC
131 | ACC_SYNTHETIC, fieldName, "Ljava/lang/Class;");
132 fv.visitEnd();
133 }
134
135 String clsName = classOptimizer.clsName;
136 mv.visitFieldInsn(GETSTATIC, clsName, fieldName, "Ljava/lang/Class;");
137 }
138
139 @Override
140 public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
141
142 String[] constructorParams;
143 if (opcode == INVOKESTATIC && name.equals("valueOf") &&
144 (constructorParams = BOXING_MAP.get(owner + desc)) != null) {
145 String type = constructorParams[0];
146 String initDesc = constructorParams[1];
147 super.visitTypeInsn(NEW, type);
148 super.visitInsn(DUP);
149 super.visitInsn((initDesc == "(J)V" || initDesc == "(D)V")? DUP2_X2: DUP2_X1);
150 super.visitInsn(POP2);
151 super.visitMethodInsn(INVOKESPECIAL, type, "<init>", initDesc, false);
152 return;
153 }
154 super.visitMethodInsn(opcode, owner, name, desc, itf);
155 }
156
157 private static final HashMap<String, String[]> BOXING_MAP;
158 static {
159 String[][] boxingNames = {
160
161 { "java/lang/Byte", "(B)V" },
162 { "java/lang/Short", "(S)V" },
163 { "java/lang/Character", "(C)V" },
164 { "java/lang/Integer", "(I)V" },
165 { "java/lang/Long", "(J)V" },
166 { "java/lang/Float", "(F)V" },
167 { "java/lang/Double", "(D)V" },
168 };
169 HashMap<String, String[]> map = new HashMap<String, String[]>();
170 for(String[] boxingName: boxingNames) {
171 String wrapper = boxingName[0];
172 String desc = boxingName[1];
173 String boxingMethod = wrapper + '(' + desc.charAt(1) + ")L" + wrapper + ';';
174 map.put(boxingMethod, boxingName);
175 }
176 BOXING_MAP = map;
177 }
178 }